package com.taokatao.cardmee.api;

import android.content.Context;
import android.text.TextUtils;

import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.taokatao.cardmee.App;
import com.taokatao.cardmee.BaseActivity;
import com.taokatao.cardmee.C;
import com.taokatao.cardmee.Utils;
import com.taokatao.cardmee.api.model.CardDetailInfo;
import com.taokatao.cardmee.api.model.CardFDInfo;
import com.taokatao.cardmee.api.model.CardFDMyCourseInfo;
import com.taokatao.cardmee.api.model.CardFDSignInfo;
import com.taokatao.cardmee.api.model.CardShareInfo;
import com.taokatao.cardmee.api.model.CardTypeInfo;
import com.taokatao.cardmee.api.model.SecretCardInfo;
import com.taokatao.cardmee.api.model.UploadCardIconInfo;
import com.taokatao.cardmee.api.model.UploadCardPictureInfo;
import com.taokatao.cardmee.api.model.UploadPhotoInfo;
import com.taokatao.cardmee.api.security.AES;
import com.taokatao.cardmee.db.model.Card;
import com.taokatao.cardmee.db.model.CardStore;
import com.taokatao.cardmee.db.model.Message;
import com.taokatao.cardmee.db.model.User;
import com.taokatao.cardmee.util.DiskLruCacheUtils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

public class ApiManager {
    private static final ApiManager instance = new ApiManager();

    public static ApiManager i() {
        return instance;
    }

    private final MediaType mMediaType = MediaType.parse("text/xml; charset=utf-8");
    private AES aesEncrypt, aesDecrypt;
    private ApiService mService;

    private ApiManager() {
        boolean debugMode = App.DEBUG_SERVICE;
        boolean debugLog = App.DEBUG_LOG;

        OkHttpClient.Builder client = new OkHttpClient.Builder();
        client.connectTimeout(5000, TimeUnit.MILLISECONDS);
        client.readTimeout(5000, TimeUnit.MILLISECONDS);
        client.writeTimeout(5000, TimeUnit.MILLISECONDS);
        client.addInterceptor(new HttpLoggingInterceptor().setLevel(debugLog ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE));
        client.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Request.Builder requestBuilder = request.newBuilder();
                requestBuilder.addHeader("OS", "Android");
                requestBuilder.addHeader("Version", String.valueOf(Utils.getAppVersionCode()));
                Utils.logd("request add Head [OS-Android][Version-%s][Brand-%s]", String.valueOf(Utils.getAppVersionCode()), android.os.Build.BRAND);
                return chain.proceed(requestBuilder.build());
            }
        });
        Retrofit mRetrofit = new Retrofit.Builder()
                .baseUrl(debugMode ? C.http.DEBUG_SERVICE_URL : C.http.RELEASE_SERVICE_URL)
                .client(client.build())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        mService = mRetrofit.create(ApiService.class);

        aesEncrypt = new AES(debugMode ? "rqowzf%%#$gbtxey" : "rqxtb%&#$jfzwoqp");
        aesDecrypt = new AES(debugMode ? "rpowzf%%#$gbtxey" : "rpxtb%&#$jfzwoqp");
    }


    private SubscriberAdapter addUnsubscribeListener(Context context, SubscriberAdapter callback) {
        if (context instanceof BaseActivity) {
            ((BaseActivity) context).registerSubscriberAdapter(callback);
        }
        return callback;
    }

    public JsonObject obtainBasicJsonObject() {
        JsonObject mJsonObject = new JsonObject();
        mJsonObject.addProperty("appId", "taokatao_app");
        mJsonObject.addProperty("appSecretKey", "fie#$%^&imvhng");
        return mJsonObject;
    }

    public String decrypt(String value) {
        return aesDecrypt.decrypt(value);
    }

    public String encrypt(String value) {
        return aesDecrypt.encrypt(value);
    }

    /**
     * 1、获取所有商家类型(商家分类，如餐饮、购物、娱乐休闲等)
     *
     * @param context  context
     * @param callback 响应回调
     */
    @SuppressWarnings("unused")
    public void queryCardType(Context context, SubscriberAdapter<RespWrapper<List<CardTypeInfo>>> callback) {
        JsonObject request = obtainBasicJsonObject();
        String strRequest = request.toString();
        Utils.logd("OkHttp queryCardType : " + strRequest);
        mService.queryCardType(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 2、获取会员卡列表
     *
     * @param context  context
     * @param uuid     系统用户id
     * @param callback 响应回调
     */
    public void queryMyCard(Context context, long uuid, SubscriberAdapter<RespWrapper<List<Card>>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("isShare", 0);
        request.addProperty("mCardCyId", 0);
        request.addProperty("pageNum", 1);
        request.addProperty("pageSize", C.http.MAX_PAGE_SIZE);
        String strRequest = request.toString();

        Utils.logd("OkHttp queryMyCard : " + strRequest);
        mService.queryMyCard(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }


    /**
     * 3、获取所有商家信息 (缓存)
     *
     * @param context  context
     * @param callback 响应回调
     */
    public void queryCardStore(Context context, long syncStartTime, SubscriberAdapter<RespWrapper<List<CardStore>>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("pageNum", 1);
        request.addProperty("pageSize", C.http.MAX_PAGE_SIZE);
        request.addProperty("timeStamp", syncStartTime);
        String strRequest = request.toString();
        Utils.logd("OkHttp queryCardStore : " + strRequest);

        final SubscriberAdapter mCallback = addUnsubscribeListener(context, callback);
        mService.queryCardStore(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new SubscriberAdapter<RespWrapper<List<CardStore>>>() {
                    @Override
                    public void onCompleted() {
                        mCallback.onCompleted();
                    }

                    @Override
                    public void onError(Throwable e) {
                        mCallback.onError(e);
                    }

                    @Override
                    public void onNext(RespWrapper<List<CardStore>> listRespWrapper) {
                        mCallback.onNext(listRespWrapper);
                        if (listRespWrapper.code == C.http.RESULT_CODE_SUCCESS) {
                            if (!TextUtils.isEmpty(listRespWrapper.message)) {
                                try {
                                    Utils.spWrite("api_queryCardStore", Long.parseLong(listRespWrapper.message));
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                });
    }

    /**
     * * 5、添加会员卡
     *
     * @param context        context
     * @param uuid           系统用户id
     * @param mCardNo        会员卡卡号 选填
     * @param mCardAliasName 会员卡别名 选填
     * @param mCardIcon      会员卡图标 选填
     * @param businessId     商家id
     * @param mCardGradeId   会员卡等级id
     * @param frontIcon      会员卡正面图片 选填
     * @param backIcon       会员卡背面图片 选填
     * @param remark         备注 选填
     * @param customBusiness 其它商家别名 选填
     * @param customPic      其它商家图片 选填
     * @param cardUser       持卡人姓名 选填
     * @param cardTel        持卡人手机号码 选填
     * @param callback       响应回调
     */
    public void addCard(Context context, long uuid, String mCardNo,
                        String mCardAliasName, String mCardIcon, long businessId,
                        long mCardGradeId, String frontIcon, String backIcon, String remark,
                        String customBusiness, String customPic, String cardUser, String cardTel, SubscriberAdapter<RespWrapper<Card>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        if (!TextUtils.isEmpty(mCardNo)) request.addProperty("mCardNo", mCardNo);
        if (!TextUtils.isEmpty(mCardAliasName))
            request.addProperty("mCardAliasName", mCardAliasName);
        if (!TextUtils.isEmpty(mCardIcon)) request.addProperty("mCardIcon", mCardIcon);
        request.addProperty("businessId", businessId);
        request.addProperty("mCardGradeId", mCardGradeId);
        if (!TextUtils.isEmpty(frontIcon)) request.addProperty("positiveIcon", frontIcon);
        if (!TextUtils.isEmpty(backIcon)) request.addProperty("backIcon", backIcon);
        if (!TextUtils.isEmpty(remark)) request.addProperty("remark", remark);
        if (!TextUtils.isEmpty(customBusiness))
            request.addProperty("anotherBusiness", customBusiness);
        if (!TextUtils.isEmpty(customPic)) request.addProperty("buPic", customPic);
        if (!TextUtils.isEmpty(cardUser)) request.addProperty("cardUser", cardUser);
        if (!TextUtils.isEmpty(cardTel)) request.addProperty("cardTel", cardTel);

        String strRequest = request.toString();
        Utils.logd("OkHttp addCard : " + strRequest);
        mService.addCard(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 6、更新我的会员卡信息
     *
     * @param context        context
     * @param uuid           系统用户id
     * @param mCardId        会员卡id
     * @param mCardAliasName 会员卡别名 选填
     * @param isShare        个人的：0，共享的：1 选填
     * @param frontIcon      会员卡正面图片 选填
     * @param backIcon       会员卡背面图片 选填
     * @param remark         备注 选填
     * @param mCardCode      会员卡编号 选填
     * @param customBusiness 其它商家别名 选填
     * @param customPic      其它商家图片 选填
     * @param cardUser       持卡人姓名 选填
     * @param cardTel        持卡人手机号码 选填
     * @param callback       响应回调
     */
    public void updateCard(Context context, long uuid, long mCardId, String mCardAliasName, Integer isShare,
                           String frontIcon, String backIcon, String remark,
                           String mCardCode,
                           String customBusiness, String customPic, String cardUser, String cardTel, SubscriberAdapter<RespWrapper<RespInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("mCardId", mCardId);
        if (mCardAliasName != null) request.addProperty("mCardAliasName", mCardAliasName);
        if (isShare != null) request.addProperty("isShare", isShare);
        if (frontIcon != null) request.addProperty("positiveIcon", frontIcon);
        if (backIcon != null) request.addProperty("backIcon", backIcon);
        if (remark != null) request.addProperty("remark", remark);
        if (mCardCode != null) request.addProperty("mCardCode", mCardCode);
        if (customBusiness != null) request.addProperty("anotherBusiness", customBusiness);
        if (customPic != null) request.addProperty("buPic", customPic);
        if (cardUser != null) request.addProperty("cardUser", cardUser);
        if (cardTel != null) request.addProperty("cardTel", cardTel);

        String strRequest = request.toString();
        Utils.logd("OkHttp updateCard : " + strRequest);
        mService.updateCard(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 7、删除我的会员卡
     *
     * @param context  context
     * @param uuid     系统用户id
     * @param mCardId  会员卡id
     *                  * @param type 卡类型(2: 通兑卡,非通兑卡不传) int 选填   传递进来的参数是 isMyCard字段 {@link Card#isMyCard}
     * @param callback 响应回调
     */
    public void deleteCard(Context context, long uuid, long mCardId,String type, SubscriberAdapter<RespWrapper<RespInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("mCardId", mCardId);

        // 卡类型(2: 通兑卡,非通兑卡不传) int 选填
        if (TextUtils.equals(type , Card.STATUS_XIAOFEI)) request.addProperty("type", "2");

        String strRequest = request.toString();
        Utils.logd("OkHttp deleteCard : " + strRequest);
        mService.deleteCard(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 8、获取会员卡分享链接
     *
     * @param context  context
     * @param uuid     系统用户id
     * @param mCardId  会员卡id
     * @param callback 响应回调
     */
    public void obtainCardShareUrl(Context context, long uuid, long mCardId, SubscriberAdapter<RespWrapper<CardShareInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("mCardId", mCardId);
        String strRequest = request.toString();
        Utils.logd("OkHttp obtainCardShareUrl : " + strRequest);
        mService.obtainCardShareUrl(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }


    /**
     * 9、取消收藏会员卡
     *
     * @param context  context
     * @param uuid     系统用户id
     * @param mCardId  会员卡id
     * @param callback 响应回调
     */
    public void cancelStarCard(Context context, long uuid, long mCardId, SubscriberAdapter<RespWrapper<RespInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("mCardId", mCardId);
        String strRequest = request.toString();
        Utils.logd("OkHttp cancelStarCard : " + strRequest);
        mService.cancelStarCard(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 10、个人中心-手机设备号静默注册
     *
     * @param context  context
     * @param callback 响应回调
     */
    public void register(Context context, SubscriberAdapter<RespWrapper<User>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("imei", Utils.getImei(context.getApplicationContext()));
        String strRequest = request.toString();
        Utils.logd("OkHttp register : " + strRequest);
        mService.register(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 11、个人中心-获取手机验证码
     *
     * @param context  context
     * @param userTel  手机号
     * @param callback 响应回调
     */
    public void obtainAuthCode(Context context, String userTel, SubscriberAdapter callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("userTel", userTel);
        String strRequest = request.toString();
        Utils.logd("OkHttp obtainAuthCode : " + strRequest);
        mService.obtainAuthCode(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 12、个人中心-绑定手机or登录
     *
     * @param context  context
     * @param userTel  手机号
     * @param callback 响应回调
     */
    public void login(Context context, long uuid, String userTel, String randomCode, SubscriberAdapter callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("userTel", userTel);
        request.addProperty("randomCode", randomCode);
        request.addProperty("imei", Utils.getImei(context.getApplicationContext()));
        String strRequest = request.toString();
        Utils.logd("OkHttp login : " + strRequest);
        mService.login(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 13、个人中心-编辑个人资料
     *
     * @param context    context
     * @param uuid       用户id
     * @param userName   用户昵称 至少传一个
     * @param headImgUrl 头像地址 至少传一个
     * @param backImgUrl 头像封面背景 至少传一个
     * @param realName   真实姓名 至少传一个 [其实必传]
     * @param birthday   生日 yyyyMMdd 至少传一个
     * @param sex        性别 至少传一个 [其实必传]
     * @param integral   积分 选填
     * @param callback   响应回调
     */
    public void updateUser(Context context, long uuid, String userName, String headImgUrl, String backImgUrl, String realName, long birthday, int sex, int integral, SubscriberAdapter<RespWrapper<RespInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        if (!TextUtils.isEmpty(userName)) request.addProperty("userName", userName);
        if (!TextUtils.isEmpty(headImgUrl)) request.addProperty("headImgUrl", headImgUrl);
        if (!TextUtils.isEmpty(backImgUrl)) request.addProperty("backImgUrl", backImgUrl);
        request.addProperty("realName", realName);
        request.addProperty("sex", sex);
        if (birthday > 0) request.addProperty("birthday", birthday);
        if (integral >= 0) request.addProperty("integral", integral);
        String strRequest = request.toString();
        Utils.logd("OkHttp updateUser : " + strRequest);
        mService.updateUser(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 15、会员卡图片上传接口
     *
     * @param context  context
     * @param iFront   卡片正面图片
     * @param iBack    卡片背面图片
     * @param callback 响应回调
     */
    public void uploadCardPicture(Context context, File iFront, File iBack, SubscriberAdapter<RespWrapper<UploadCardPictureInfo>> callback) {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();

        MultipartBody.Builder builder = new MultipartBody.Builder();
        if (iFront != null) {
            String contentTypeFor = fileNameMap.getContentTypeFor(iFront.getAbsolutePath());
            if (contentTypeFor == null) contentTypeFor = "application/octet-stream";
            builder.addFormDataPart("positiveIcon", iFront.getName(), RequestBody.create(MediaType.parse(contentTypeFor), iFront));
        }
        if (iBack != null) {
            String contentTypeFor = fileNameMap.getContentTypeFor(iBack.getAbsolutePath());
            if (contentTypeFor == null) contentTypeFor = "application/octet-stream";
            builder.addFormDataPart("backIcon", iBack.getName(), RequestBody.create(MediaType.parse(contentTypeFor), iBack));
        }

        RequestBody requestBody = builder.build();

        Utils.logd("OkHttp uploadCardPicture : ~");
        mService.uploadCardPicture(requestBody).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 16、用户头像上传接口
     *
     * @param context    context
     * @param photo      上传的头像图片
     * @param background 上传的头像背景图片
     * @param callback   响应回调
     */
    public void uploadAvatar(Context context, File photo, File background, SubscriberAdapter<RespWrapper<UploadPhotoInfo>> callback) {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        MultipartBody.Builder builder = new MultipartBody.Builder();
        if (photo != null) {
            String contentTypeFor = fileNameMap.getContentTypeFor(photo.getAbsolutePath());
            if (contentTypeFor == null) contentTypeFor = "application/octet-stream";
            builder.addFormDataPart("headIcon", photo.getName(), RequestBody.create(MediaType.parse(contentTypeFor), photo));
        }
        if (background != null) {
            String contentTypeFor = fileNameMap.getContentTypeFor(background.getAbsolutePath());
            if (contentTypeFor == null) contentTypeFor = "application/octet-stream";
            builder.addFormDataPart("backIcon", background.getName(), RequestBody.create(MediaType.parse(contentTypeFor), background));
        }

        RequestBody requestBody = builder.build();

        Utils.logd("OkHttp uploadAvatar : ~");
        mService.uploadAvatar(requestBody).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 16、用户头像上传接口
     *
     * @param context  context
     * @param icon     上传的商家标识图片
     * @param callback 响应回调
     */
    public void uploadCardIcon(Context context, File icon, SubscriberAdapter<RespWrapper<UploadCardIconInfo>> callback) {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        String contentTypeFor = fileNameMap.getContentTypeFor(icon.getAbsolutePath());
        if (contentTypeFor == null) contentTypeFor = "application/octet-stream";

        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.addFormDataPart("busIcon", icon.getName(), RequestBody.create(MediaType.parse(contentTypeFor), icon));

        RequestBody requestBody = builder.build();

        Utils.logd("OkHttp uploadCardIcon : ~");
        mService.uploadCardIcon(requestBody).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 22、获取会员卡详细信息
     *
     * @param context    context
     * @param uuid       系统用户id 必填
     * @param cardId     会员卡ID 必填
     * @param businessId 商家ID 必填
     * @param sid        商家分店ID 选填
     * @param type 卡类型(2: 通兑卡,非通兑卡不传) int 选填   传递进来的参数是 isMyCard字段 {@link Card#isMyCard}
     * @param callback   响应回调
     */
    public void obtainCardDetail(Context context, long uuid, long cardId, long businessId, Long sid, String type , SubscriberAdapter<RespWrapper<CardDetailInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("cardId", cardId);
        request.addProperty("businessId", businessId);
        if (sid != null && sid > 0) request.addProperty("sid", sid);

        // 卡类型(2: 通兑卡,非通兑卡不传) int 选填
        if (TextUtils.equals(type , Card.STATUS_XIAOFEI)) request.addProperty("type", "2");

        String strRequest = request.toString();
        Utils.logd("OkHttp obtainCardDetail : " + strRequest);
        final String cacheKey = "obtainCardDetail#" + strRequest;
        DiskLruCacheUtils cacheUtils = App.i().getHttpCacheUtils();
        String cacheResult = Utils.inputStreamToString(cacheUtils.read(cacheKey));

        if (cacheResult != null) {
            RespWrapper<CardDetailInfo> cacheResp = App.i().getGson().fromJson(cacheResult, new TypeToken<RespWrapper<CardDetailInfo>>() {
            }.getType());
            Utils.logd("obtainCardDetail#onNext cache");
            callback.onNext(cacheResp);
        }
        final SubscriberAdapter<RespWrapper<CardDetailInfo>> mCallback = addUnsubscribeListener(context, callback);
        mService.obtainCardDetail(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new SubscriberAdapter<RespWrapper<CardDetailInfo>>() {
                    @Override
                    public void onCompleted() {
                        mCallback.onCompleted();
                    }

                    @Override
                    public void onError(Throwable e) {
                        mCallback.onError(e);
                    }

                    @Override
                    public void onNext(RespWrapper<CardDetailInfo> listRespWrapper) {
                        Utils.logd("obtainCardDetail#onNext data");
                        mCallback.onNext(listRespWrapper);
                        if (C.http.RESULT_CODE_SUCCESS == listRespWrapper.code) {
                            DiskLruCacheUtils cacheUtils = App.i().getHttpCacheUtils();
                            cacheUtils.write(cacheKey, new ByteArrayInputStream(App.i().getGson().toJson(listRespWrapper).getBytes()));
                        }
                    }
                });
    }

    /**
     * 21、会员卡使用次数
     *
     * @param context  context
     * @param cardId   会员卡id
     * @param reqType  请求类型  1:访问卡详情（默认）；2:扫码使用
     * @param callback 响应回调
     */
    public void updateCardUseCount(Context context, long cardId, int reqType, SubscriberAdapter<RespWrapper<RespInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("mCardId", cardId);
        request.addProperty("reqType", reqType);

        String strRequest = request.toString();
        Utils.logd("OkHttp updateCardUseCount : " + strRequest);
        mService.updateCardUseCount(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 25、扫码添加会员卡（商家版）
     *
     * @param context  context
     * @param uuid     系统用户id
     * @param storeId  商家id
     * @param callback 响应回调
     */
    public void scanToAddMemberCard(Context context, long uuid, long storeId, SubscriberAdapter<RespWrapper<Card>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("storeId", storeId);

        String strRequest = request.toString();
        Utils.logd("OkHttp scanToAddMemberCard : " + strRequest);
        mService.scanToAddMemberCard(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 26、扫码领取会员卡--确认
     *
     * @param context  context
     * @param uuid     系统用户id
     * @param cardId   用户输入的秘钥串 必填
     * @param realName 用户真实姓名
     * @param callback 响应回调
     */
    public void scanToAddCardConfirm(Context context, long uuid, long cardId, String realName, SubscriberAdapter<RespWrapper<RespInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("cardId", cardId);
        request.addProperty("realName", realName);

        String strRequest = request.toString();
        Utils.logd("OkHttp scanToAddCardConfirm : " + strRequest);
        mService.scanToAddCardConfirm(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 27、秘钥获得会员卡信息
     *
     * @param context      context
     * @param uuid         系统用户id
     * @param secretCardNo 用户输入的秘钥串 必填
     * @param realName 用户真实姓名
     * @param callback     响应回调
     */
    public void secretToAddCard(Context context, long uuid, String secretCardNo, SubscriberAdapter<RespWrapper<SecretCardInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("secretCardNo", secretCardNo);

        String strRequest = request.toString();
        Utils.logd("OkHttp secretToAddCard : " + strRequest);
        mService.secretToAddCard(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }


    /**
     * 28、秘钥领取会员卡--确认
     *
     * @param context       context
     * @param uuid          系统用户id
     * @param consumeCardId 消费卡id 必填
     *                      @param realName 用户真实姓名
     * @param callback      响应回调
     */
    public void secretToAddCardConfirm(Context context, long uuid, long consumeCardId, String realName, SubscriberAdapter<RespWrapper<RespInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("consumeCardId", consumeCardId);
        request.addProperty("realName", realName);

        String strRequest = request.toString();
        Utils.logd("OkHttp secretToAddCardConfirm : " + strRequest);
        mService.secretToAddCardConfirm(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }


    /**
     * 29、获取我的商家消息列表
     *
     * @param context   context
     * @param uuid      系统用户id
     * @param timeStamp 时间戳(预留做增量更新)
     * @param callback  响应回调
     */
    public void getMyMessageList(Context context, long uuid, long timeStamp, SubscriberAdapter<RespWrapper<List<Message>>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("timeStamp", timeStamp);

        String strRequest = request.toString();
        Utils.logd("OkHttp getMyMessageList : " + strRequest);


        final SubscriberAdapter mCallback = addUnsubscribeListener(context, callback);
        mService.getMyMessageList(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new SubscriberAdapter<RespWrapper<List<Message>>>() {
                    @Override
                    public void onCompleted() {
                        mCallback.onCompleted();
                    }

                    @Override
                    public void onError(Throwable e) {
                        mCallback.onError(e);
                    }

                    @Override
                    public void onNext(RespWrapper<List<Message>> listRespWrapper) {
                        mCallback.onNext(listRespWrapper);
                        if (listRespWrapper.code == C.http.RESULT_CODE_SUCCESS) {
                            if (!TextUtils.isEmpty(listRespWrapper.message)) {
                                try {
                                    Utils.spWrite("api_getMyMessageList", Long.parseLong(listRespWrapper.message));
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                });
    }


    /**
     * 30、获取商品套餐详情
     *
     * @param context    context
     * @param uuid       系统用户id 必填
     * @param sid        商家分店ID 必填
     * @param cardId     会员卡ID 必填
     * @param businessId 商家ID 必填
     *                   @param type (2: 通兑卡,非通兑卡不传)  int 选填   传递进来的参数是 isMyCard字段 {@link Card#isMyCard}
     * @param callback   响应回调
     */
    public void getMcardProductDetails(Context context, long uuid, long cardId, long businessId, long sid, String type ,  SubscriberAdapter<RespWrapper<CardFDInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("cardId", cardId);
        request.addProperty("businessId", businessId);
        request.addProperty("sid", sid);

        // 卡类型(2: 通兑卡,非通兑卡不传) int 选填
        if (TextUtils.equals(type , Card.STATUS_XIAOFEI)) request.addProperty("type", "2");

        String strRequest = request.toString();
        final String cacheKey = "getMcardProductDetails#" + strRequest;
        DiskLruCacheUtils cacheUtils = App.i().getHttpCacheUtils();
        String cacheResult = Utils.inputStreamToString(cacheUtils.read(cacheKey));

        if (cacheResult != null) {
            RespWrapper<CardFDInfo> cacheResp = App.i().getGson().fromJson(cacheResult, new TypeToken<RespWrapper<CardFDInfo>>() {
            }.getType());
            Utils.logd("getMcardProductDetails#onNext cache");
            callback.onNext(cacheResp);
        }
        final SubscriberAdapter<RespWrapper<CardFDInfo>> mCallback = addUnsubscribeListener(context, callback);
        mService.getMcardProductDetails(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new SubscriberAdapter<RespWrapper<CardFDInfo>>() {
                    @Override
                    public void onCompleted() {
                        Utils.logd("getMcardProductDetails#onCompleted");
                        mCallback.onCompleted();
                    }

                    @Override
                    public void onError(Throwable e) {
                        Utils.loge("getMcardProductDetails#onError");
                        mCallback.onError(e);
                    }

                    @Override
                    public void onNext(RespWrapper<CardFDInfo> listRespWrapper) {
                        Utils.logd("getMcardProductDetails#onNext data");
                        mCallback.onNext(listRespWrapper);
                        if (C.http.RESULT_CODE_SUCCESS == listRespWrapper.code) {
                            DiskLruCacheUtils cacheUtils = App.i().getHttpCacheUtils();
                            cacheUtils.write(cacheKey, new ByteArrayInputStream(App.i().getGson().toJson(listRespWrapper).getBytes()));
                        }
                    }
                });
    }


    /**
     * 32、获取商家课程列表
     *
     * @param context    context
     * @param uuid       系统用户id 必填
     * @param cardId     卡片id 必填
     * @param sid        分店id  必填
     * @param searchTime 检索开始日期 格式YYYY-MM-dd
     * @param callback   响应回调
     */
    public void getBranchCourseList(Context context, long uuid, long cardId, long sid, String searchTime, SubscriberAdapter<RespWrapper<List<CardFDMyCourseInfo>>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("sid", sid);
        request.addProperty("cardId", cardId);
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
        try {
            String searchValue = sdf2.format(sdf1.parse(searchTime));
            request.addProperty("searchTime", searchValue);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        String strRequest = request.toString();
        Utils.logd("OkHttp getBranchCourseList : " + strRequest);
        mService.getBranchCourseList(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }


    /**
     * 33、用户预约商家课程
     *
     * @param context  context
     * @param uuid     系统用户id 必填
     * @param cardId   卡片id 必填
     * @param sid      分店id  必填
     * @param courseId 课程id 必填
     * @param type     类型 1预约;2候补 必填 , 3取消预约 ，4 取消候补
     * @param callback 响应回调
     */
    public void orderBranchCourse(Context context, long uuid, long cardId, long sid, long courseId, int type, SubscriberAdapter<RespWrapper<RespInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("sid", sid);
        request.addProperty("cardId", cardId);
        request.addProperty("courseId", courseId);
        request.addProperty("type", type);

        String strRequest = request.toString();
        Utils.logd("OkHttp orderBranchCourse : " + strRequest);
        mService.orderBranchCourse(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }


    /**
     * 34、用户签到获得列表(主动扫码)
     *
     * @param context  context
     * @param uuid     系统用户id 必填
     * @param cardId   卡片id 必填
     * @param sid      分店id  必填
     * @param callback 响应回调
     */
    public void userActiveSign(Context context, long uuid, long sid, SubscriberAdapter<RespWrapper<List<CardFDMyCourseInfo>>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("sid", sid);

        String strRequest = request.toString();
        Utils.logd("OkHttp userActiveSign : " + strRequest);
        mService.userActiveSign(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 35、用户扫码签到-确认
     *
     * @param context      context
     * @param uuid         系统用户id 必填
     * @param cardId       cardId  必填
     * @param sid          分店id  必填
     * @param courseInfoId 用户预约课程id(对应34号接口返回的courseInfoId)
     * @param courseId     课程id(对应34号接口返回的courseId)
     * @param callback     响应回调
     */
    public void userActiveSignConfirm(Context context, long uuid, long cardId, long sid, long courseInfoId, long courseId, SubscriberAdapter<RespWrapper<CardFDSignInfo>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("cardId", cardId);
        request.addProperty("sid", sid);
        if (courseInfoId > 0) request.addProperty("courseInfoId", courseInfoId);
        if (courseId > 0) request.addProperty("courseId", courseId);

        String strRequest = request.toString();
        Utils.logd("OkHttp userActiveSignConfirm : " + strRequest);
        mService.userActiveSignConfirm(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }

    /**
     * 24、被扫二维码格式
     *
     * 二维码格式：<br>
     * http://wap.taokatao.cn:64559/wapServer/bussiness/downAddSign.do?storeId=1(测试)  <br>
     *  http://c.flow360.cn:4559/wapServer/bussiness/downAddSign.do?storeId=1(正式)<br>
     *  如果匹配到和上面链接下划线部分一致的url就发出下面的请求<br>
     *  请求地址：<br>
     *  http://域名:端口/wapServer/bussiness/addSign.do<br>
     */
    public void addSign(Context context, long uuid, long storeId,SubscriberAdapter<RespWrapper<String>> callback) {
        JsonObject request = obtainBasicJsonObject();
        request.addProperty("uuid", uuid);
        request.addProperty("storeId", storeId);

        String strRequest = request.toString();
        Utils.logd("OkHttp addSign : " + strRequest);
        mService.addSign(RequestBody.create(mMediaType, aesEncrypt.encrypt(strRequest)))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(addUnsubscribeListener(context, callback));
    }


}



